import 'package:flutter/material.dart';
import 'package:top_foundation/utils/util.dart';

import 'type.dart';

class GroupedListView extends StatefulWidget {
  const GroupedListView({
    Key? key,
    this.sectionCount = 1,
    this.sectionHeight,
    required this.itemCount,
    required this.sectionBuilder,
    required this.itemBuilder,
    this.header,
    this.footer,
    this.controller,
    this.physics,
    this.shrinkWrap = false,
    this.padding,
    this.onRefresh,
    this.onLoading,
    this.refreshTopInset,
    this.backgroundColor,
  }) : super(key: key);
  final int sectionCount;
  final ItemCount itemCount;
  final SectionHeight? sectionHeight;
  final IndexedWidgetBuilder sectionBuilder;
  final ItemBuilder itemBuilder;
  final Widget? header;
  final Widget? footer;
  final ScrollController? controller;
  final ScrollPhysics? physics;
  final bool? shrinkWrap;
  final VoidCallback? onRefresh;
  final VoidCallback? onLoading;
  final EdgeInsets? padding;
  final double? refreshTopInset;
  final Color? backgroundColor;

  @override
  State<GroupedListView> createState() => _GroupedListViewState();
}

class _GroupedListViewState extends State<GroupedListView> {
  var currSection = 0.obs;
  var viewDidLoad = false;
  final ScrollController sc = ScrollController();
  List<GlobalKey> keys = [];
  List<double> offsets = [];

  @override
  void initState() {
    super.initState();
    updateInitialization();
    sc.addListener(() {
      if (offsets.isEmpty) {
        return;
      }
      var i = offsets
          .lastIndexWhere((element) => (sc.offset > element && element != 0));
      if (i == -1) {
        i = 0;
      }

      var of = offsets[i];
      if (currSection.value != i && of != 0) {
        currSection.value = i;
        var n = i + 1;
        if (offsets.length > n && offsets[n] == 0) {
          var e = keys[n];
          final obj = e.currentContext!.findRenderObject() as RenderBox;

          var offset = obj.localToGlobal(Offset.zero).dy -
              Get.statusBarHeight -
              44 +
              obj.size.height +
              sc.offset;
          offsets[n] = offset;
        }
      }
    });
  }

  void updateInitialization() {
    if (keys.length == widget.sectionCount && keys.isNotEmpty) {
      return;
    }
    keys = List.generate(
      widget.sectionCount,
      (index) => GlobalKey(
        debugLabel: index.toString(),
      ),
    );
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      viewDidLoad = true;
      offsets = keys.map((e) {
        if (e.currentContext == null) {
          return 0.0;
        }
        final obj = e.currentContext!.findRenderObject() as RenderBox;
        var offset = obj.localToGlobal(Offset.zero);
        return offset.dy - Get.statusBarHeight - 44 + obj.size.height;
      }).toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return getList(context);
  }

  Widget getList(BuildContext context) {
    updateInitialization();
    List<Widget> items = [];

    for (var i = 0; i < widget.sectionCount; i++) {
      if (widget.sectionHeight != null &&
          widget.sectionHeight!(i) > 0 &&
          i > 0) {
        items.add(Container(
          key: keys[i],
          child: widget.sectionBuilder(context, i),
        ));
      }
      var _itemCount = widget.itemCount(i);
      if (_itemCount > 0) {
        for (var j = 0; j < _itemCount; j++) {
          items.add(widget.itemBuilder(i, j));
        }
      }
    }
    if (widget.footer != null) {
      items.add(widget.footer!);
    }

    return Container(
      padding: widget.padding ?? EdgeInsets.zero,
      color: widget.backgroundColor,
      child: Column(
        children: [
          if (widget.header != null) widget.header!,
          if (keys.isNotEmpty)
            Obx(
              () => SizedBox(
                width: Get.width,
                key: keys.first,
                child: widget.sectionBuilder(context, currSection.value),
              ),
            ),
          Expanded(
            child: ListView(
              controller: sc,
              children: items,
            ),
          ),
        ],
      ),
    );
  }
}

class GroupedListSectionDelegate extends SliverPersistentHeaderDelegate {
  final double height;
  final Widget Function(double) builder;
  GroupedListSectionDelegate({
    required this.builder,
    required this.height,
  });

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return builder(shrinkOffset);
  }

  @override
  double get maxExtent => height;

  @override
  double get minExtent => height;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return true;
  }
}
